package week07.shadingspherejdbc;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.replicaquery.api.config.ReplicaQueryRuleConfiguration;
import org.apache.shardingsphere.replicaquery.api.config.rule.ReplicaQueryDataSourceRuleConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author edward
 * @since 2021-08-08
 */
@Configuration
@EnableJdbcRepositories(basePackages = {"week07.springjdbc", "week07.shadingspherejdbc"})
@EnableTransactionManagement
@ComponentScan(basePackages = {"week07.springjdbc", "week07.shadingspherejdbc"})
public class ShadingSphereAppConfig extends AbstractJdbcConfiguration {

    @Bean
    public DataSource getDataSourceShadingSphere() {
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put("master", createDataSource());
        dataSourceMap.put("slave", createDataSource());
        ReplicaQueryDataSourceRuleConfiguration dataSourceConfig = new ReplicaQueryDataSourceRuleConfiguration(
                "read_write_ds", "master", Arrays.asList("master", "slave"), null);
        ReplicaQueryRuleConfiguration ruleConfig = new ReplicaQueryRuleConfiguration(Collections.singleton(dataSourceConfig), Collections.emptyMap());
        try {
            return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(ruleConfig), new Properties());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return createDataSource();
    }

    @Bean
    public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }

    @Bean
    public TransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    @Bean
    JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    private DataSource createDataSource() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName("com.mysql.cj.jdbc.Driver");
        config.setJdbcUrl("jdbc:mysql://127.0.0.1:3301/camp");
        config.setUsername("root");
        config.setPassword("");
        return new HikariDataSource(config);
    }
}
